﻿//反射 Reflection
//是.net框架提供的一个机制
//是一种在运行时动态获取类型信息、创建对象、调用方法或访问属性的机制
//它通过分析程序集的元数据来实现对代码的动态操作
//.net提供一组API，允许我们在运行时访问这些元数据
//反射的核心用途
//1.动态获取类型信息，如类、接口、方法、属性等
//2.运行时创建对象实例，即使类型在编译时未知
//3.调用方法、访问字段或属性，甚至操作私有成员
//4.实现插件系统、依赖注入、序列化、反序列化等动态场景

//优点
//通过反射，可以动态地创建对象、调用方法、访问字段和属性
//缺点
//反射操作通常比直接代码调用要慢，因为它需要在运行时解析类型信息。
//过度使用反射可能会使代码变得难以理解和维护
using System.Reflection;//反射核心命名空间
public class Program
{
    public static void Main()
    {
        //获取类型信息
        //1.typeof 编译时静态获取类型
        //直接获取类型的元数据，不需要实例
        // Type type1 = typeof(string);
        // Console.WriteLine($"typeof:{type1.Name}");

        // //2.通过对象实例.GetType()
        // //是Object类的方法，运行时动态获取实例的实际类型
        // var s = "Hello";
        // Type type2 = s.GetType();
        // Console.WriteLine($"GetType():{type2.Name}");

        // //3.通过类型全名获取，需要包含命名空间、
        // //需要完整类型名，适用于跨程序集类型查询
        // Type type3 = Type.GetType("System.Int32");
        // Console.WriteLine($"Type.GetType():{type3.Name}");


        // //动态创建对象实例
        // Type type = typeof(Person);
        // //1.Activator.CreateInstance创建无参构造实例
        // //如果类型没有无参构造器会抛出异常
        // object obj1 = Activator.CreateInstance(type);
        // Console.WriteLine(((Person)obj1).Name);

        // //2.Activator.CreateInstance创建带参构造实例
        // //参数按顺序传递，类型必须匹配构造函数签名
        // object obj2 = Activator.CreateInstance(type, "张三");
        // Console.WriteLine(((Person)obj2).Name);

        // //3.ConstructorInfo精确控制构造函数
        // //GetConstructor()匹配参数类型数组
        // //Invoke()触发构造过程
        // var ctor = type.GetConstructor(new[] { typeof(string) });
        // object obj3 = ctor.Invoke(new object[] { "李四" });
        // Console.WriteLine(((Person)obj3).Name);

        // //利用反射访问成员（方法、属性、私有字段）
        // //创建student实例，使用无参构造
        // object student = Activator.CreateInstance(typeof(Student));
        // //1.反射调用方法
        // MethodInfo method = typeof(Student).GetMethod("PrintInfo");
        // method.Invoke(student, null);//无参时传入null

        // //2.利用反射操作属性
        // PropertyInfo prop = typeof(Student).GetProperty("Name");
        // prop.SetValue(student, "Bob");//设置属性值
        // Console.WriteLine(prop.GetValue(student));//获取属性值

        // //3.利用反射访问私有字段
        // //BindingFlags.NonPublic：搜索非公共成员
        // //BindingFlags.Instance：搜索实例成员
        // FieldInfo field = typeof(Student).GetField("_score",
        //     BindingFlags.NonPublic | BindingFlags.Instance);
        // field.SetValue(student, 95);//修改私有字段值
        // method.Invoke(student, null);

        // Type testType = typeof(TestClass);
        // //获取类上标记的自定义特性
        // var attr = (MyCustomAttribute)testType.GetCustomAttribute(typeof(MyCustomAttribute));
        // Console.WriteLine(attr.Description);

        //创建整数类型的Box实例
        Box<int> intBox = new Box<int>(42);
        Console.WriteLine($"整数内容：{intBox.GetContent()}");
        //创建字符串类型的Box实例
        Box<string> stringBox = new Box<string>("Hello World");
        Console.WriteLine($"字符串内容：{stringBox.GetContent()}");
        //创建自定义对象类型的Box实例
        Person person = new Person("Bob", 25);
        Box<Person> personBox = new Box<Person>(person);
        Console.WriteLine($"人物信息：{personBox.GetContent().Name},{personBox.GetContent().Age}");
    }
}

// public class Person
// {
//     public string Name { get; set; }
//     public Person() => Name = "Unknown";
//     public Person(string name) => Name = name;
// }

public class Student
{
    private int _score = 90;
    public string Name { get; set; } = "Tom";
    public void PrintInfo() => Console.WriteLine($"Name:{Name},Score:{_score}");
}
[AttributeUsage(AttributeTargets.Class)]
public class MyCustomAttribute : Attribute
{
    public string Description { get; }
    public MyCustomAttribute(string desc) => Description = desc;
}

[MyCustom("这是一个测试类")]
public class TestClass { }


//泛型类
public class Box<T>
{
    private T content;//使用类型参数定义字段

    //构造函数使用类型参数
    public Box(T content)
    {
        this.content = content;
    }
    //方法返回类型为类型参数
    public T GetContent()
    {
        return content;
    }
    //方法参数使用类型参数
    public void UpdateContent(T newContent)
    {
        content = newContent;
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Person(string name, int age)
    {
        Name = name;
        Age = age;        
    }
}